import { PrismaService } from 'src/common/prisma/PrismaService';
import { PostDto } from '../dto/PostDto';
import { plainToInstance } from 'class-transformer';
import { Injectable } from '@nestjs/common';
import PostQueryParam from '../param/PostQueryParam';
import PageResult from 'src/common/PageResult';
import { Util } from 'src/common/Util';
import ServiceException from 'src/common/ServiceException';

/*
 * @Author: jingfuu@163.com
 * @Date: 2024-11-12 14:23:40
 * @LastEditTime: 2024-12-16 09:59:42
 * @Description: 职位service
 */
@Injectable()
export class PostService {
  constructor(private prisma: PrismaService) {}

  async getIdsByUserId(userId: number) {
    const postIds = await this.prisma.sysUserPost.findMany({
      where: {
        userId: userId,
      },
      select: {
        postId: true,
      },
    });
    return postIds.map((item) => item.postId);
  }

  async getAllPost() {
    const postList = await this.prisma.sysPost.findMany();
    return plainToInstance(PostDto, postList);
  }
  async getByUserId(userId: number) {
    const postIds = await this.prisma.sysUserPost.findMany({
      where: {
        userId: userId,
      },
      select: {
        postId: true,
      },
    });
    const postList = await this.prisma.sysPost.findMany({
      where: {
        postId: {
          in: postIds.map((item) => item.postId),
        },
        status: '0',
      },
    });
    return plainToInstance(PostDto, postList);
  }

  async getById(id: number): Promise<PostDto> {
    const post = await this.prisma.sysPost.findUnique({
      where: {
        postId: id,
      },
    });
    return plainToInstance(PostDto, post);
  }

  async getByIds(ids: number[]): Promise<PostDto[]> {
    const posts = await this.prisma.sysPost.findMany({
      where: {
        postId: {
          in: ids,
        },
      },
    });
    return plainToInstance(PostDto, posts);
  }

  async updateUserPost(userId: number, postIds: number[]) {
    await this.prisma.sysUserPost.deleteMany({
      where: {
        userId: userId,
      },
    });
    await this.prisma.sysUserPost.createMany({
      data: postIds.map((item) => ({
        postId: item,
        userId: userId,
      })),
    });
  }

  async list(param: PostQueryParam): Promise<PageResult<PostDto>> {
    const skip = param.pageNum != 0 ? (param.pageNum - 1) * param.pageSize : 0;
    const whereClause: any = this.generatePostQueryCondition(param);
    const [total, posts] = await this.prisma.$transaction([
      this.prisma.sysPost.count({ where: whereClause }),
      this.prisma.sysPost.findMany({
        skip,
        take: param.pageSize,
        orderBy: {
          postSort: 'asc',
        },
        where: whereClause,
      }),
    ]);
    const rows: PostDto[] = plainToInstance(PostDto, posts);
    return {
      total,
      rows,
    };
  }
  private generatePostQueryCondition(param: PostQueryParam): any {
    const whereClause: any = {};

    if (param.postName) {
      whereClause.postName = {
        contains: param.postName,
      };
    }

    if (param.postCode !== undefined) {
      whereClause.postCode = param.postCode;
    }

    if (param.status !== undefined) {
      whereClause.status = param.status;
    }
    return whereClause;
  }

  async deletePost(id: number) {
    await this.prisma.sysPost.delete({
      where: { postId: id },
    });
  }

  async exportPost(param: PostQueryParam) {
    const whereClause: any = this.generatePostQueryCondition(param);
    const sysPosts = await this.prisma.sysPost.findMany({
      orderBy: {
        createTime: 'desc',
      },
      where: whereClause,
    });
    const postDtos = plainToInstance(PostDto, sysPosts);
    // 设置列头
    const header = [
      { header: '岗位序号', key: 'id', width: 10 },
      { header: '岗位编码', key: 'postName', width: 20 },
      { header: '岗位名称', key: 'postCode', width: 20 },
      { header: '岗位排序', key: 'postSort', width: 20 },
      { header: '状态', key: 'status', width: 20 },
    ];
    const posts = postDtos.map((post) => {
      return {
        id: post.postId,
        postName: post.postName,
        postCode: post.postCode,
        postSort: post.postSort,
        status: post.status == '0' ? '正常' : '停用',
      };
    });
    return Util.excelExport(posts, header);
  }

  async detail(id: number) {
    const sysPost = this.prisma.sysPost.findUnique({
      where: { postId: id },
    });
    return plainToInstance(PostDto, sysPost);
  }

  async updatePost(post: PostDto) {
    await this.checkPostKey(post.postCode, post.postId);
    await this.checkPostName(post.postName, post.postId);
    await this.prisma.sysPost.update({
      where: { postId: post.postId },
      data: {
        postName: post.postName,
        postCode: post.postCode,
        postSort: post.postSort,
        status: post.status,
        remark: post.remark,
      },
    });
  }
  async checkPostKey(postCode: string, postId: number) {
    const post = await this.prisma.sysPost.findFirst({
      where: { postCode: postCode },
    });
    if (!postId) {
      if (post) {
        throw new ServiceException('岗位编码' + postCode + '已存在');
      }
    } else {
      if (post && post.postId != postId) {
        throw new ServiceException('岗位编码' + postCode + '已存在');
      }
    }
  }

  async checkPostName(postName: string, postId: number) {
    const post = await this.prisma.sysPost.findFirst({
      where: { postName: postName },
    });
    if (!postId) {
      if (post) {
        throw new ServiceException('岗位' + postName + '已存在');
      }
    } else {
      if (post && post.postId != postId) {
        throw new ServiceException('岗位' + postName + '已存在');
      }
    }
  }

  async createPost(post: PostDto) {
    await this.checkPostKey(post.postCode, null);
    await this.checkPostName(post.postName, null);
    await this.prisma.sysPost.create({
      data: {
        postName: post.postName,
        postCode: post.postCode,
        postSort: post.postSort,
        status: post.status,
        remark: post.remark,
      },
    });
  }
}
